﻿using MiscLib;
using System;
using System.Collections.Generic;
using System.Data;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using System.Web;
using System.Drawing;

namespace FCBLL
{
    public class ExcelCompare
    {
        public void Compare(DataTable dt_1, DataTable dt_2, out Dictionary<int, int> left_pos, out Dictionary<int, int> right_pos)
        {
            int _left_pos = 0;
            int _right_pos = 0;
            left_pos = new Dictionary<int, int>();
            right_pos = new Dictionary<int, int>();

            #region 比较
            foreach (DataRow dr_1 in dt_1.Rows)
            {
                int i = 0;
                bool flag;
                for (i = _right_pos; i < dt_2.Rows.Count; i++)
                {
                    if (CompareDR(dr_1, dt_2.Rows[i], out flag) || flag)
                    {
                        if (i < dt_2.Rows.Count && i == _right_pos)
                        {
                            _right_pos = i + 1;
                            break;
                        }
                        else if (i < dt_2.Rows.Count && i > _right_pos)
                        {
                            if (left_pos.ContainsKey(_left_pos))
                            {
                                left_pos[_left_pos] = i - _right_pos;
                            }
                            else
                            {
                                left_pos.Add(_left_pos, i - _right_pos);
                            }
                            _right_pos = i + 1;
                            break;
                        }
                    }
                }
                if (i == dt_2.Rows.Count)
                {
                    if (right_pos.ContainsKey(_right_pos))
                    {
                        right_pos[_right_pos] += 1;
                    }
                    else
                    {
                        right_pos.Add(_right_pos, 1);
                    }
                }
                _left_pos++;
            }
            #endregion
        }

        public bool CompareDR(DataRow dr_1, DataRow dr_2, out bool flag)
        {
            flag = true;
            bool iflag = true;
            foreach (DataColumn dc in dr_1.Table.Columns)
            {
                if (!dr_1[dc.ColumnName].ToString().Trim().Equals(dr_2[dc.ColumnName].ToString().Trim()))
                {
                    iflag = false;
                    if (dc.ColumnName.Equals("Footprint") || dc.ColumnName.Equals("Manufacturer") || dc.ColumnName.Equals("Manufacturer-No.")) flag = false;//new
                }
            }
            return iflag;
        }

        public DataTable DataTableChange(DataTable dt, Dictionary<int, int> _pos)
        {
            int _rowsIndex = 0;
            foreach (KeyValuePair<int, int> s in _pos)
            {
                for (int i = 0; i < s.Value; i++)
                {
                    DataRow dr = dt.NewRow();
                    dt.Rows.InsertAt(dr, s.Key + _rowsIndex);
                }
                _rowsIndex += s.Value;
            }
            return dt;
        }

        public Dictionary<int, string> Compared(DataTable dt_1, DataTable dt_2)
        {
            Dictionary<int, string> colDic = new Dictionary<int, string>();

            for (int i = 0; i < dt_1.Rows.Count; i++)
            {
                DataRow dr_1 = dt_1.Rows[i];
                DataRow dr_2 = dt_2.Rows[i];
                if ((isRowNull(dr_1) && !isRowNull(dr_2)) || (!isRowNull(dr_1) && isRowNull(dr_2)))
                {
                    colDic.Add(i, "green");
                    continue;
                }
                for (int j = 0; j < 7; j++)
                {
                    if (!dt_1.Rows[i][j].ToString().Trim().Equals(dt_2.Rows[i][j].ToString().Trim()))
                    {
                        colDic.Add(i, "red");
                        break;
                    }
                }
            }
            return colDic;
        }

        protected bool isRowNull(DataRow dr)
        {
            int i = 0;
            foreach (DataColumn dc in dr.Table.Columns)
            {
                if (dr[dc.ColumnName].ToString().Trim().Equals(string.Empty)) i++;
            }
            if (i == 7) return true;
            else return false;
        }

        public DataView ToDataView(DataTable dt_1, DataTable dt_2)
        {
            DataTable dt = new DataTable();
            dt.Columns.Add("Quantity_1", Type.GetType("System.String"));
            dt.Columns.Add("Populate_1", Type.GetType("System.String"));
            dt.Columns.Add("Designator_1", Type.GetType("System.String"));
            dt.Columns.Add("Description_1", Type.GetType("System.String"));
            dt.Columns.Add("Footprint_1", Type.GetType("System.String"));
            dt.Columns.Add("Manufacturer_1", Type.GetType("System.String"));
            dt.Columns.Add("Manufacturer_No._1", Type.GetType("System.String"));
            dt.Columns.Add("Quantity_2", Type.GetType("System.String"));
            dt.Columns.Add("Populate_2", Type.GetType("System.String"));
            dt.Columns.Add("Designator_2", Type.GetType("System.String"));
            dt.Columns.Add("Description_2", Type.GetType("System.String"));
            dt.Columns.Add("Footprint_2", Type.GetType("System.String"));
            dt.Columns.Add("Manufacturer_2", Type.GetType("System.String"));
            dt.Columns.Add("Manufacturer_No._2", Type.GetType("System.String"));

            for (int i = 0; i < dt_1.Rows.Count; i++)
            {
                DataRow dr = dt.NewRow();
                for (int j = 0; j < 7; j++)
                {
                    dr[j] = dt_1.Rows[i][j].ToString();
                    dr[j + 7] = dt_2.Rows[i][j].ToString();
                }
                dt.Rows.Add(dr);
            }
            return new DataView(dt);
        }

        public string OutputExcel(DataView dv, string path, string filename_1, string filename_2, HttpResponse Response, HttpServerUtility Server, Dictionary<int, string> colDic, Dictionary<int, List<int>> redDic)
        {
            filename_1 = filename_1.Replace(".xls", "");
            filename_2 = filename_2.Replace(".xls", "");
            filename_1 = filename_1.Replace(" ", "");
            filename_2 = filename_2.Replace(" ", "");
            string FullFileName = path + filename_1 + "_compare_" + filename_2 + ".xlsx";
            GC.Collect();
            Microsoft.Office.Interop.Excel.Application excel = new Microsoft.Office.Interop.Excel.Application();
            //excel.Visible = true;
            Microsoft.Office.Interop.Excel._Workbook xBk;
            Microsoft.Office.Interop.Excel._Worksheet xSt;
            try
            {
                // WriteLog(logPath, "进入生成excel4");
                int excelColNum = dv.ToTable().Columns.Count;
                if (excelColNum < 21)
                    excelColNum = 21;
                xBk = excel.Workbooks.Add(true);
                xSt = (Microsoft.Office.Interop.Excel._Worksheet)xBk.ActiveSheet;
                //取消网格线               
                excel.ActiveWindow.DisplayGridlines = false;
                //设置显示比例
                excel.ActiveWindow.Zoom = 70;
                //设置字体

                #region 表头
                Microsoft.Office.Interop.Excel.Range rg = xSt.Range[excel.Cells[1, 1], excel.Cells[200, 20]];
                rg.Font.Size = 14;
                rg.Font.Name = "Times New Roman";
                rg.HorizontalAlignment = Microsoft.Office.Interop.Excel.XlHAlign.xlHAlignCenter;
                rg.VerticalAlignment = Microsoft.Office.Interop.Excel.XlHAlign.xlHAlignCenter;

                //设置行高
                rg.RowHeight = 33;
                //第1行
                int i = 0;
                foreach (DataColumn dc in dv.Table.Columns)
                {
                    excel.Cells[1, ++i] = dc.ColumnName;
                }
                rg = xSt.Range[excel.Cells[1, 1], excel.Cells[1, dv.Table.Columns.Count]];
                rg.Font.Size = 16;
                rg.Font.Bold = true;
                rg.Cells.Interior.Pattern = Microsoft.Office.Interop.Excel.Constants.xlSolid;
                rg.Cells.Interior.PatternColorIndex = Microsoft.Office.Interop.Excel.Constants.xlAutomatic;
                rg.Cells.Interior.Color = 12632256;
                rg.Cells.Interior.TintAndShade = 0;
                rg.Cells.Interior.PatternTintAndShade = 0;
                #endregion

                #region content
                rg = xSt.Range[excel.Cells[2, 1], excel.Cells[1 + dv.Table.Rows.Count, dv.Table.Columns.Count]];
                rg.Select();
                object[,] objData = new Object[dv.Count, dv.Table.Columns.Count];
                for (i = 0; i < dv.Count; i++)
                {
                    for (int j = 0; j < dv.ToTable().Columns.Count; j++)
                    {
                        objData[i, j] = dv[i][j];
                    }
                }
                rg.Value2 = objData;

                foreach (KeyValuePair<int, string> item in colDic)
                {
                    rg = xSt.Range[excel.Cells[item.Key+2, 1], excel.Cells[item.Key+2, dv.Table.Columns.Count]];
                    rg.Cells.Interior.Pattern = Microsoft.Office.Interop.Excel.Constants.xlSolid;
                    rg.Cells.Interior.PatternColorIndex = Microsoft.Office.Interop.Excel.Constants.xlAutomatic;
                    rg.Cells.Interior.Color = 11857588;
                    rg.Cells.Interior.TintAndShade = 0;
                    rg.Cells.Interior.PatternTintAndShade = 0;
                    if (redDic.Keys.Contains(item.Key))
                    {
                        List<int> li = redDic[item.Key];
                        i = 0;
                        foreach (int s in li)
                        {
                            Microsoft.Office.Interop.Excel.Range rg1 = xSt.Range[excel.Cells[item.Key + 2, s + 1], excel.Cells[item.Key + 2, s + 1]];
                            Microsoft.Office.Interop.Excel.Range rg2 = xSt.Range[excel.Cells[item.Key + 2, s + 8], excel.Cells[item.Key + 2, s + 8]];
                            rg1.Cells.Interior.PatternColorIndex = Microsoft.Office.Interop.Excel.Constants.xlAutomatic;
                            rg2.Cells.Interior.PatternColorIndex = Microsoft.Office.Interop.Excel.Constants.xlAutomatic;
                            rg1.Cells.Interior.Color = 16738922;
                            rg2.Cells.Interior.Color = 16738922;
                        }
                    }

                }
                #endregion
                rg = xSt.Range[excel.Cells[1, 1], excel.Cells[dv.Count, dv.Table.Columns.Count]];
                rg.ColumnWidth = 40;
                rg = xSt.Range[excel.Cells[1, 1], excel.Cells[dv.Count, 2]];
                rg.ColumnWidth = 20;
                rg = xSt.Range[excel.Cells[1, 8], excel.Cells[dv.Count, 9]];
                rg.ColumnWidth = 20;
                rg = xSt.Range[excel.Cells[1, 6], excel.Cells[dv.Count, 6]];
                rg.ColumnWidth = 20;
                rg = xSt.Range[excel.Cells[1, 13], excel.Cells[dv.Count, 13]];
                rg.ColumnWidth = 20;
                rg = xSt.Range[excel.Cells[1, 1], excel.Cells[1, dv.Table.Columns.Count]];
                rg.Select();



                //   WriteLog(logPath, "进入生成excel8");
                System.IO.FileInfo fi = new System.IO.FileInfo(FullFileName);
                if (!System.IO.Directory.Exists(fi.DirectoryName))
                    System.IO.Directory.CreateDirectory(fi.DirectoryName);
             //   WriteLog(logPath, "进入生成excel9");

                if (System.IO.File.Exists(FullFileName))
                {
                    File.Delete(FullFileName);
                }
              //  WriteLog(logPath, "进入生成excel10");
                xBk.SaveCopyAs(FullFileName);
                dv = null;
                xBk.Close(false, null, null);
                excel.Quit();
            }
            catch (Exception ex)
            {

            }
            finally
            {
               //rg = null;
               //xSt = null;
               //xBk = null;
               //excel = null;
                try
                {
                    Kill_Excel(excel);
                }
                catch { ; }
                GC.Collect();
            }
            return FullFileName;
        }

        public Dictionary<int, List<int>> CompareDetail(Dictionary<int, string> colDic, DataTable dt_1, DataTable dt_2)
        {
            Dictionary<int, List<int>> redDic = new Dictionary<int,List<int>>();
            foreach (KeyValuePair<int, string> item in colDic)
            {
                if (item.Value == "red")
                {
                    DataRow dr_1 = dt_1.Rows[item.Key];
                    DataRow dr_2 = dt_2.Rows[item.Key];
                    int i=0;
                    List<int> li = new List<int>();
                    foreach (DataColumn dc in dt_1.Columns)
                    {
                        if (!dr_1[dc.ColumnName].Equals(dr_2[dc.ColumnName]))
                        {
                            li.Add(i++);
                        }
                        else
                        {
                            i++;
                        }
                    }
                    redDic.Add(item.Key, li);
                }
            }
            return redDic;
        }

        [DllImport("User32.dll", CharSet = CharSet.Auto)]
        private static extern int GetWindowThreadProcessId(IntPtr hwnd, out int ID);
        private static void Kill_Excel(Microsoft.Office.Interop.Excel.Application excel)
        {
            IntPtr t = new IntPtr(excel.Hwnd);   //得到这个句柄，具体作用是得到这块内存入口 
            int k = 0;
            GetWindowThreadProcessId(t, out k);   //得到本进程唯一标志k
            if (k == 0)    //由于权限不足 获取不到PID时
            {
                System.Diagnostics.Process[] p = System.Diagnostics.Process.GetProcessesByName("Excel");
                foreach (Process process in p)
                {
                    process.Kill();
                }
            }
            else
            {
                System.Diagnostics.Process p = System.Diagnostics.Process.GetProcessById(k);   //得到对进程k的引用
                p.Kill();     //关闭进程k
            }
        }
    }
}
